﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MongoDB.Bson;
using Moq;
using Newtonsoft.Json;
using Sustainalytics.Entities;
using Sustainalytics.Portfolios.BL.Model;
using Sustainalytics.ScreeningTool.BL;
using Sustainalytics.Utils;

namespace Sustainalytics.ScreeningTool.Service.Tests
{
    [TestClass()]
    public class RunResultControllerTests
    {
        ScreeningToolApplication app;
        
        [TestInitialize]
        public void SetUp()
        {
            this.app = new ScreeningToolApplication();
            this.app.EnsureInitialized();
        }

        [TestCleanup]
        public void TearDown()
        {
            this.app.Dispose();
            this.app = null;
        }



        //TODO: Septi check this TEST (Ileana changed ClientPortfolio mock to PortfolioDetails mock - we don't have UserId in PortfolioDetails)
        [TestMethod]
        public void GetWithPortfolioId_Returns_DuplicatedResults_ForSecuritiesInClientPortfolio()
        {

            #region comment

            //List<ResultOutput> mockResultOutput = new List<ResultOutput>() { 
            //    new ResultOutput()
            //    {
            //        CompanyId = Guid.NewGuid(),
            //        CompanyName = "TestCompany1",
            //        Ticker = "12093",
            //        Exchange = "Thamse",
            //        FilterId = Guid.Empty,
            //        Id = Guid.NewGuid(),
            //        IsValid = ResultIsValid.Valid,
            //        Criteria = new List<CriteriaResultOutput>() 
            //        { 
            //            new CriteriaResultOutput() { Name = "Ticker",  StringValue = "12093", IsValid = ResultIsValid.Valid }, 
            //            new CriteriaResultOutput() { Name = "CompanyName", StringValue = "TestCompany1", IsValid = ResultIsValid.Valid }, 
            //            new CriteriaResultOutput() { Name = "TotalEmployee", StringValue = string.Empty, IsValid = ResultIsValid.Valid }, 
            //        }
            //    },
            //    new ResultOutput()
            //    {
            //        CompanyId = Guid.NewGuid(),
            //        CompanyName = "TestCompany2",
            //        FilterId = Guid.Empty,
            //        Exchange = "SomeExchange",
            //        Ticker = "12354",
            //        Id = Guid.NewGuid(),
            //        Criteria = new List<CriteriaResultOutput>()
            //        {
            //            new CriteriaResultOutput() { Name = "Ticker", StringValue = "12093", IsValid = ResultIsValid.NotValid }, 
            //            new CriteriaResultOutput() { Name = "CompanyName", StringValue = "TestCompany1", IsValid = ResultIsValid.NotValid }, 
            //            new CriteriaResultOutput() { Name = "TotalEmployee", StringValue = string.Empty, IsValid = ResultIsValid.Valid }, 
            //        }
            //    },
            //    new ResultOutput()
            //    {
            //        CompanyId = Guid.NewGuid(),
            //        CompanyName = "TestCompany3",
            //        FilterId = Guid.Empty,
            //        Exchange = "SomeExchange3",
            //        Ticker = "3554",
            //        Id = Guid.NewGuid(),
            //        Criteria = new List<CriteriaResultOutput>()
            //        {
            //            new CriteriaResultOutput() { Name = "Ticker", StringValue = "12093", IsValid = ResultIsValid.NotValid }, 
            //            new CriteriaResultOutput() { Name = "CompanyName", StringValue = "TestCompany1", IsValid = ResultIsValid.NotValid }, 
            //            new CriteriaResultOutput() { Name = "TotalEmployee", StringValue = string.Empty, IsValid = ResultIsValid.NotValid }, 
            //        }
            //    }
            //};

            #endregion

            //Arrange

            Guid filterId = Guid.NewGuid();

            List<BsonDocument> mockResultOutput = new List<BsonDocument>();

                var comp1Id = new Guid("876a92aa-bfcd-e411-8883-f0921c109468");
                mockResultOutput.Add(new BsonDocument()
                {
                    { "CompanyId", comp1Id },
                    { "CompanyName", "SC Iprolam SA" },
                    { "Ticker", "12093" },
                    { "Exchange", "Thamse" },
                    { "FilterId" , filterId },
                    { "Id" , Guid.NewGuid() },
                    { "IsValid" , ResultIsValid.Valid },
                    { "Fields", ""},
                    { "Criteria" , new BsonArray()
                        { 
                            new BsonDocument() { {"Name", "Ticker"},  {"StringValue", "12093"}, {"IsValid", ResultIsValid.Valid} }, 
                            new BsonDocument() { {"Name", "CompanyName"}, {"StringValue", "TestCompany1"}, {"IsValid", ResultIsValid.Valid} }, 
                            new BsonDocument() { {"Name", "TotalEmployee"}, {"StringValue", string.Empty}, {"IsValid", ResultIsValid.Valid} }, 
                        }.ToJson()
                    }
                });

                var comp2Id = new Guid("a22bdbab-5e67-4b7b-b47b-b2476520498d");
                mockResultOutput.Add(new BsonDocument()
                {
                    { "CompanyId", comp2Id},
                    { "CompanyName", "BioFarm SA"},
                    { "FilterId", filterId},
                    { "Exchange", "SomeExchange"},
                    { "Ticker", "12354"},
                    { "Id", Guid.NewGuid()},
                    { "IsValid" , ResultIsValid.ValidAndNotValid },
                    { "Fields", ""},
                    { "Criteria", new BsonArray()
                        {
                            new BsonDocument() { {"Name", "Ticker"}, {"StringValue", "12093"}, {"IsValid", ResultIsValid.NotValid} }, 
                            new BsonDocument() { {"Name", "CompanyName"}, {"StringValue", "TestCompany1"}, {"IsValid", ResultIsValid.NotValid} }, 
                            new BsonDocument() { {"Name", "TotalEmployee"}, {"StringValue", string.Empty}, {"IsValid", ResultIsValid.Valid} }, 
                        }.ToJson()
                    }
                });

                var comp3Id = new Guid("c55f48c0-1a84-4957-b9d4-c5e437ca70d5");
                mockResultOutput.Add(new BsonDocument()
                {
                    { "CompanyId", comp3Id },
                    { "CompanyName", "SC Bermas SA"},
                    { "FilterId", filterId},
                    { "Exchange", "SomeExchange3"},
                    { "Ticker", "3554"},
                    { "Id", Guid.NewGuid()},
                    { "IsValid" , ResultIsValid.NotValid },
                    { "Fields", ""},
                    { "Criteria", new BsonArray()
                        {
                            new BsonDocument() { {"Name", "Ticker"}, {"StringValue", "12093"}, {"IsValid", ResultIsValid.NotValid} }, 
                            new BsonDocument() { {"Name", "CompanyName"}, {"StringValue", "TestCompany1"}, {"IsValid", ResultIsValid.NotValid} }, 
                            new BsonDocument() { {"Name", "TotalEmployee"}, {"StringValue", string.Empty}, {"IsValid", ResultIsValid.NotValid} }, 
                        }.ToJson()
                    }
                });
            
            List<BsonDocument> mockScreeningData = new List<BsonDocument>()
            {
                new BsonDocument()
                {
                    { "_id", comp1Id },
                    { "CompanyName", "SC Iprolam SA" },
                    { "MainExchange", "Thamse" },
                    { "MainTicker", "12093" },
                },

                new BsonDocument() {
                    { "_id", comp2Id },
                    { "CompanyName", "BioFarm SA" },
                    { "MainExchange", "SomeExchange" },
                    { "MainTicker", "12354" },
                },

                new BsonDocument() {
                    { "_id", comp3Id },
                    { "CompanyName", "SC Bermas SA" },
                    { "MainExchange", "SomeExchange3" },
                    { "MainTicker", "3554" },
                }
            };


            List<PortfolioSecurityModel> mockPortfolioDetails = new List<PortfolioSecurityModel>()
            {
                new PortfolioSecurityModel()
                { 
                    //UserId = new Guid("876a92aa-bfcd-e411-8883-f0921c109468"), 
                    DisplayInfo = new DisplayInformation
                    {
                        CustomSecurityIdentifierName = "SC Iprolam SA", 
                        SecurityIdentifier = "IQ47842915", 
                    },
                    MatchedInfo = new MatchedInformation
                    {
                        CapitalIQId = "47842915", 
                        CompanyName = "SC Iprolam SA"
                    },
                    CompanyId = comp1Id, 
                },

                new PortfolioSecurityModel() 
                { 
                    //UserId = new Guid("876a92aa-bfcd-e411-8883-f0921c109468"), 
                    DisplayInfo = new DisplayInformation
                    {
                        CustomSecurityIdentifierName = "BioFarm SA", 
                        SecurityIdentifier = "IQ24932555", 
                    },
                    MatchedInfo = new MatchedInformation
                    {
                        CapitalIQId = "24932555", 
                        CompanyName = "BioFarm SA"
                    },
                    CompanyId = comp2Id, 
                },

                new PortfolioSecurityModel() 
                { 
                    //UserId = new Guid("876a92aa-bfcd-e411-8883-f0921c109468"), 
                    DisplayInfo = new DisplayInformation
                    {
                        CustomSecurityIdentifierName = "SC Bermas SA", 
                        SecurityIdentifier = "IQ20333656", 
                    },
                    MatchedInfo = new MatchedInformation
                    {
                        CapitalIQId = "20333656", 
                        CompanyName = "SC Bermas SA"
                    },
                    CompanyId = comp3Id, 
                },

                new PortfolioSecurityModel() 
                { 
                    //UserId = new Guid("876a92aa-bfcd-e411-8883-f0921c109468"), 
                    DisplayInfo = new DisplayInformation
                    {
                        CustomSecurityIdentifierName = "SC Bermas SA isin", 
                        SecurityIdentifier = "5600267", 
                    },
                    MatchedInfo = new MatchedInformation
                    {
                        CapitalIQId = "20333656",
                        CompanyName = "SC Bermas SA"
                    },
                    CompanyId = comp3Id, 
                },

                new PortfolioSecurityModel() 
                { 
                    //UserId = new Guid("876a92aa-bfcd-e411-8883-f0921c109468"), 
                    DisplayInfo = new DisplayInformation
                    {
                        CustomSecurityIdentifierName = "SC Bermas SA sedol", 
                        SecurityIdentifier = "IQ116738255", 
                    },
                    MatchedInfo = new MatchedInformation
                    {
                        CapitalIQId = "20333656", 
                        CompanyName = "SC Bermas SA"
                    },
                    CompanyId = comp3Id, 
                },
            };


            RunResultsOptionsDto options = new RunResultsOptionsDto
            {
                GetCount = false,
                IsValid = ResultIsValid.Valid,
                PortfolioId = new Guid("a0fd9501-249e-4909-94fb-e9e9023cb522"),
                OrderAscending = true,
                Skip = 0,
                Take = 100,
                OrderBy = null
            };

            ResultOutputFilter filter = new ResultOutputFilter
            {
                FilterId = filterId,
                IsValid = options.IsValid
            };


            var mockICompanyScreening = new Mock<ICompanyScreening>();

            mockICompanyScreening.Setup(x => x.GetClientPortfolioSecurities(It.Is<Guid>(p=>p==options.PortfolioId.Value),It.IsAny<PortfolioUserClaims>()))
                .Returns(mockPortfolioDetails);

            //mockICompanyScreening.Setup(x => x.GetResultOutput(filter, options.Skip, options.Take, options.OrderBy, options.OrderAscending))
            //    .Returns(mockResultOutput);

            mockICompanyScreening.Setup(x => x.GetResultOutput(It.IsAny<ResultOutputFilter>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string[]>(), It.IsAny<bool>()))
                .Returns(mockResultOutput);

            //mockICompanyScreening.Setup(x => x.GetScreeningDataFields(It.IsAny<List<string>>(), It.IsAny<List<Guid>>()))
            //    .Returns(mockScreeningData.ToDictionary(c => c["_id"].AsGuid, c => c));

            var controller = new RunResultsController(mockICompanyScreening.Object);

            controller.Request = new HttpRequestMessage();
            controller.Request.SetConfiguration(new HttpConfiguration());

            //Act
            var response = controller.Get(filterId, options);

            //Assert
            string jsonString = response.Content.ReadAsStringAsync().Result;
            GetRunResultDto actualResult = JsonConvert.DeserializeObject<GetRunResultDto>(jsonString);

            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
            Assert.AreEqual(mockResultOutput.Count + mockPortfolioDetails.Count, actualResult.Items.Count);
        }


        [TestMethod]
        public void WhenGetMethod_isCalled_ResultsOfThePriviousRun_AreReturned()
        {
            //var sentFilterId = Guid.NewGuid();
            //var receivedFilterId = Guid.Empty;
            //List<ResultOutput> returnedResults = null;

            //RunResultsOptionsDto options = new RunResultsOptionsDto
            //{
            //    GetCount = false,
            //    IsValid = ResultIsValid.Valid,
            //    OrderAscending = true,
            //    Skip = 0,
            //    Take = 100,
            //    OrderBy = null
            //};


            //var companyScreeningService = new Sustainalytics.ScreeningTool.BL.Fakes.StubICompanyScreening()
            //{
            //    GetResultOutputResultOutputFilterInt32Int32StringArrayBoolean = (filter, skip,  take, orderBy, asc) =>
            //    {
            //        receivedFilterId = filter.FilterId ?? Guid.Empty;
            //        List<ResultOutput> resultOutput = new List<ResultOutput>();
            //        resultOutput.Add(new ResultOutput()
            //        {
            //            CompanyId = Guid.NewGuid(),
            //            CompanyName = "TestCompany1",
            //            Ticker = "12093",
            //            Exchange = "Thamse",
            //            FilterId = receivedFilterId,
            //            Id = Guid.NewGuid(),
            //            IsValid = ResultIsValid.Valid,
            //            Criteria = new List<CriteriaResultOutput>() 
            //            { 
            //                new CriteriaResultOutput() { Name = "Ticker", NumericValue = 0, StringValue = "12093", ValueType = CriteriaValueType.String, IsValid = ResultIsValid.Valid }, 
            //                new CriteriaResultOutput() { Name = "CompanyName", NumericValue = 0, StringValue = "TestCompany1", ValueType = CriteriaValueType.String, IsValid = ResultIsValid.Valid }, 
            //                new CriteriaResultOutput() { Name = "TotalEmployee", NumericValue = 15000, StringValue = string.Empty, ValueType = CriteriaValueType.Numeric, IsValid = ResultIsValid.Valid }, 
            //            }
            //        });
            //        resultOutput.Add(new ResultOutput()
            //        {
            //            CompanyId = Guid.NewGuid(),
            //            CompanyName = "TestCompany2",
            //            FilterId = receivedFilterId,
            //            Exchange = "SomeExchange",
            //            Ticker = "12354",
            //            Id = Guid.NewGuid(),
            //            Criteria = new List<CriteriaResultOutput>()
            //            {
            //                new CriteriaResultOutput() { Name = "Ticker", NumericValue = 0, StringValue = "12093", ValueType = CriteriaValueType.String, IsValid = ResultIsValid.NotValid }, 
            //                new CriteriaResultOutput() { Name = "CompanyName", NumericValue = 0, StringValue = "TestCompany1", ValueType = CriteriaValueType.String, IsValid = ResultIsValid.NotValid }, 
            //                new CriteriaResultOutput() { Name = "TotalEmployee", NumericValue = 12000, StringValue = string.Empty, ValueType = CriteriaValueType.Numeric, IsValid = ResultIsValid.Valid }, 
            //            }
            //        });
            //        resultOutput.Add(new ResultOutput()
            //        {
            //            CompanyId = Guid.NewGuid(),
            //            CompanyName = "TestCompany3",
            //            FilterId = receivedFilterId,
            //            Exchange = "SomeExchange3",
            //            Ticker = "3554",
            //            Id = Guid.NewGuid(),
            //            Criteria = new List<CriteriaResultOutput>()
            //            {
            //                new CriteriaResultOutput() { Name = "Ticker", NumericValue = 0, StringValue = "12093", ValueType = CriteriaValueType.String, IsValid = ResultIsValid.NotValid }, 
            //                new CriteriaResultOutput() { Name = "CompanyName", NumericValue = 0, StringValue = "TestCompany1", ValueType = CriteriaValueType.String, IsValid = ResultIsValid.NotValid }, 
            //                new CriteriaResultOutput() { Name = "TotalEmployee", NumericValue = 25000, StringValue = string.Empty, ValueType = CriteriaValueType.Numeric, IsValid = ResultIsValid.NotValid }, 
            //            }
            //        });
            //        returnedResults = resultOutput;
            //        return resultOutput;
            //    }
            //};

            //var runresultController = Utils.setupController(new RunResultsController(companyScreeningService));

            //var response = runresultController.Get(sentFilterId, options);

            //var expected = new { Count = 0, Items = returnedResults, Options = options };

            //Assert.AreEqual(receivedFilterId, sentFilterId, "The filter sent is different than the expected one.");
            //Assert.IsTrue(response.AreExpected(HttpStatusCode.OK, expected), "The httpResponse is not as expected.");

         
        }
       
    }
}
